package com.uw.uwregistry.cluster;


import com.uw.uwregistry.config.UwRegistryConfigProperties;
import com.uw.uwregistry.meta.ServerMeta;
import com.uw.uwregistry.service.RegistryContainer;
import com.uw.uwregistry.util.IpUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;

import java.util.ArrayList;
import java.util.List;

/**
 * 集群管理
 */
@Slf4j
public class Cluster {


    @Value("${server.port}")
    private String port;

    private ServerMeta self;


    @Getter
    private List<ServerMeta> nodeList;

    private final ClusterMonitor clusterMonitor;
    private final UwRegistryConfigProperties uwRegistryConfigProperties;


    public Cluster(UwRegistryConfigProperties uwRegistryConfigProperties) {
        this.uwRegistryConfigProperties = uwRegistryConfigProperties;
        this.clusterMonitor = new ClusterMonitor(this);
    }


    public void start() {
        // 初始化注册中心集群节点信息
        String host = IpUtil.getHost();
        this.self = initSelfNode(host);
        this.nodeList = initServerNodeList(host);

        this.clusterMonitor.start();
    }

    public void stop() {
        this.clusterMonitor.stop();
    }

    private ServerMeta initSelfNode(String host) {
        return ServerMeta.builder().url("http://" + host + ":" + port).status(true).version(-1L).build();
    }

    @NotNull
    private List<ServerMeta> initServerNodeList(String host) {
        List<ServerMeta> nodeList = new ArrayList<>();
        for (String serverNode : uwRegistryConfigProperties.getNodeList()) {
            ServerMeta serverMeta = new ServerMeta();
            if (serverNode.contains("localhost")) {
                serverNode = serverNode.replace("localhost", host);
            } else if (serverNode.contains("127.0.0.1")) {
                serverNode = serverNode.replace("127.0.0.1", host);
            }


            if (serverNode.equals(self.getUrl())) {
                nodeList.add(self);
                continue;
            }

            serverMeta.setUrl(serverNode);
            serverMeta.setStatus(false);
            serverMeta.setLeader(false);
            serverMeta.setVersion(-1L);

            nodeList.add(serverMeta);
        }
        return nodeList;
    }


    public ServerMeta leader() {
        return nodeList.stream()
                .filter(ServerMeta::isStatus)
                .filter(ServerMeta::isLeader)
                .findFirst()
                .orElse(null);
    }

    public ServerMeta self() {
        self.setVersion(RegistryContainer.containerVersion());
        return self;
    }

}
